package com.alibaba.citrus.cr.price.ability.facade;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Response;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.crplatformenhance.credit.dto.DeleteRequest;
import com.epoch.app.crplatformenhance.credit.model.Credit;
import com.epoch.app.crplatformenhance.credit.service.CreditService;
import com.epoch.app.crplatformenhance.model.dto.CreditLoadListRequest;
import com.epoch.app.crpricecenter.api.creditwrite.service.CreditWriteService;
import com.epoch.app.crpricecenter.model.dto.CreditCallbackRequest;
import com.epoch.app.crpricecenter.model.dto.MnSap020CallbackSDO;
import com.epoch.app.crpricecenter.model.dto.SapMessageHeader;
import com.epoch.app.crunifiedinventory.api.allocateapplyorderread.dto.QueryAllowPlacedOrderAmountRequest;
import com.epoch.app.crunifiedinventory.api.allocateapplyorderread.service.AllocateApplyOrderReadService;
import com.epoch.app.crunifiedinventory.api.allocateorderread.dto.QueryFrozenAndUnconfirmedAmountRequest;
import com.epoch.app.crunifiedinventory.api.allocateorderread.service.AllocateOrderReadService;
import com.epoch.app.crunifiedinventory.model.dto.AllowPlacedOrderAmountResponse;
import com.epoch.app.crunifiedinventory.model.dto.FrozenAndUnconfirmedAmountResponse;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @description: SAP020分子公司对集团查询信贷 回调接收
 * @author: yuhw
 * @date: 2023年05月22日 10:49
 **/
@Service
@Primary
public class CreditWriteServiceImpl implements CreditWriteService {
    private static Log log = Log.getLogger(CreditWriteServiceImpl.class);

    @Resource
    private EpochCacheService epochCacheService;
    @Resource
    private BaseDataService baseDataService;
    @Resource
    private AllocateApplyOrderReadService allocateApplyOrderReadService;
    @Resource
    private AllocateOrderReadService allocateOrderReadService;
    @Resource
    private CreditService creditService;

    //时间戳缓存key
    private static final String CREDIT_CALLBACK_REQUEST_TIME = "CREDIT_CALLBACK_REQUEST_TIME";
    //回调分布式锁key
    private static final String CREDIT_CALLBACK_KEY = "CREDIT_CALLBACK_KEY";
    private static final String SPLIT = "_";
    //设置sap时间戳过期时间为
    private static final Long SAP_TIMESTAMP_CACHE_EXPIRE = 60 * 60 * 24 * 7L;
    //分布式锁超时时间
    private static final Long TIMEOUT_MSECS = 5 * 60 * 1000L;
    //分布式锁过期时间
    private static final Long EXPIRE_MSECS = 10 * 60 * 1000l;
    //销售组织6000
    private static final String SALE_ORGANIZATION_CODE = "6000";
    //分析渠道20
    private static final String SAP_CHANNEL = "20";
    //货品组
    private static final String PRODUCT_GROUP_CODE = "11";
    //负号
    private static final String NEGATIVE = "-";
    //页面刷新按钮触发020请求sap信贷key
    private static final String REFRESH_CREDIT_QUERY_KEY = "REFRESH_CREDIT_QUERY_KEY";

    /**
     * SAP020分子公司对集团查询信贷回调数据接口
     * @param callbackRequest
     * @return
     */
    @Override
    @FacadeInvoker(value = "信贷查询回调")
    @EpochTransactional(appCode="cr_forecast_sales", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Result<Boolean> callback(CreditCallbackRequest callbackRequest) {
        log.info("CreditWriteServiceImpl_request:{}", JSON.toJSONString(callbackRequest));
        //查询回调接口数据是否完整
        //判断是否接收数据
        checkRequest(callbackRequest);
        Map<String, OrganizationSDO> organizationMap = getOrganizationMap(callbackRequest);
        Set<Boolean> resultSet = Sets.newHashSet();
        //还需要加分布式锁, key固定
        callbackRequest.getData().forEach(sdo -> {
            if (sdo.getSoldPartCode() == null){
                resultSet.add(false);
                return;
            }
            try(RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(),CREDIT_CALLBACK_KEY + SPLIT + sdo.getSoldPartCode(),
                    TIMEOUT_MSECS,EXPIRE_MSECS)){
                if (!lock.lock()){
                    throw new FacadeException("OTS-07-008-01-16-021");
                }
                //校验参数
                checkParams(sdo);
                String soldPartCode = sdo.getSoldPartCode().toString();
                if (!organizationMap.containsKey(soldPartCode)){
                    throw new FacadeException("OTS-07-008-01-16-027");
                }
                //成功 or失败请求
                String requestTime = callbackRequest.getMessageHeader().getSENDTIME();
                //根据时间戳判断是否跳过请求
                if (skip(soldPartCode,requestTime)){
                    throw new FacadeException("OTS-07-008-01-16-032");
                }
                //删除原有的页面刷新
//                deleteRefreshCache(sdo.getSoldPartCode().toString());
                //处理数据
                handleData(sdo);
                //设置时间戳
                //重试就算了吧 毕竟这个也比较实时性 再调用一下就可以了.
                updateRequestTimeCache(soldPartCode,requestTime);
            }catch (Throwable e){
                log.error("CreditWriteServiceImpl_callback_error,companyId={}",JSON.toJSONString(sdo),e);
                resultSet.add(false);
            }
        });
        if (resultSet.contains(false)){
            return Result.fail("OTS-07-008-01-16-030","同步处理分子公司对集团信贷数据异常");
        }
        return Result.success(true);
    }

    /**
     * 是否跳过请求
     * 回调的时间戳早于之前的时间戳则跳过, 只处理最新的
     * @param requestTime
     * @return
     */
    private boolean skip(String soldPartCode,String requestTime){
        //获取时间戳
        String cacheRequestTime = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),
                CREDIT_CALLBACK_REQUEST_TIME + SPLIT + soldPartCode);
        if (StringUtils.isBlank(cacheRequestTime)){
            return false;
        }
        //当前时间戳早于(等于)缓存时间戳,则跳过此次请求
        return earlierThanOrEqualTo(requestTime,cacheRequestTime);
    }

    /**
     *  判断当前请求时间戳 是否早于(等于)缓存时间戳
     * @param requestTime
     * @param cacheRequestTime
     * @return
     */
    private boolean earlierThanOrEqualTo(String requestTime,String cacheRequestTime){
        return requestTime.compareTo(cacheRequestTime) <= 0;
    }

    /**
     * 更新时间戳
     * @param requestTime
     */
    private void updateRequestTimeCache(String soldPartCode,String requestTime){
        if (StringUtils.isBlank(requestTime)){
            return;
        }
        boolean setSuccess = epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(),
                CREDIT_CALLBACK_REQUEST_TIME + SPLIT + soldPartCode, requestTime,
                SAP_TIMESTAMP_CACHE_EXPIRE,
                TimeUnit.SECONDS);
        if (!setSuccess){
            throw new FacadeException("OTS-07-008-01-16-023");
        }
    }
    //清除页面刷新按钮的缓存
    private void deleteRefreshCache(String soldPartCode){
        if (StringUtils.isBlank(soldPartCode)){
            return;
        }
        epochCacheService.remove(BcOrderConstants.REDIS_CACHE_CODE(),Lists.newArrayList(REFRESH_CREDIT_QUERY_KEY + soldPartCode));
    }
    //处理数据
    private void handleData(MnSap020CallbackSDO sdo){
        //先load数据 删除后新增
        Credit credit = buildCredit(sdo);
        deleteOldData(sdo.getSoldPartCode().toString());
        creditService.create(credit);
    }

    //删除分子公司可发货余额的老数据
    private void deleteOldData(String soldPartCode){
        CreditLoadListRequest creditLoadListRequest = new CreditLoadListRequest();
        creditLoadListRequest.setSoldPartCode(soldPartCode);
        Result<List<Credit>> listResult = creditService.loadList(creditLoadListRequest);
        if (listResult !=null && CollectionUtils.isNotEmpty(listResult.getResult())){
            listResult.getResult().forEach(credit -> {
                DeleteRequest deleteRequest = new DeleteRequest();
                deleteRequest.setId(credit.getId());
                creditService.delete(deleteRequest);
            });
        }
    }

    /**
     * 填充信贷/分子公司可发货余额数据
     * @param credit
     */
    private void fillCredit(Credit credit){
        AllowPlacedOrderAmountResponse allowPlacedOrderAmountResponse = getAllowPlacedOrderAmountResponse(credit.getCompanyId());
        FrozenAndUnconfirmedAmountResponse frozenAndUnconfirmedAmountResponse = getFrozenAndUnconfirmedAmountResponse(credit.getCompanyId());
        //已冻结金额
        credit.setFrozenOrderAmount(frozenAndUnconfirmedAmountResponse.getFrozenOrderAmount());
        //未确认未冻结金额
        credit.setUnfrozenUnconfirmedOrderAmount(frozenAndUnconfirmedAmountResponse.getUnfrozenUnconfirmedOrderAmount());
        //未确认及冻结金额 = 已冻结金额 + 未确认未冻结金额
        credit.setUnconfirmedAndFrozenOrderAmount(getBigDecimal(frozenAndUnconfirmedAmountResponse.getFrozenOrderAmount())
                .add(getBigDecimal(frozenAndUnconfirmedAmountResponse.getUnfrozenUnconfirmedOrderAmount()))
                .setScale(2,RoundingMode.HALF_UP).toPlainString());

        //客户实际可发货余额 = 可发货余额+未确认及冻结金额
        credit.setCustomerActualAvailableAmount(getBigDecimal(credit.getAvailableBalance()).add(getBigDecimal(credit.getUnconfirmedAndFrozenOrderAmount()))
                .setScale(2,RoundingMode.HALF_UP).toPlainString());
        //可下预报订单金额
        credit.setPendingReplyOrderAmount(allowPlacedOrderAmountResponse.getPendingReplyOrderAmount());
        credit.setPartReplyOrderAmount(allowPlacedOrderAmountResponse.getPartReplyOrderAmount());
//      //取相反数  可下预报订单金额=：-客户实际可发货金额-已创建的调拨预报单金额
        credit.setAllowPlacedOrderAmount(getBigDecimal(credit.getCustomerActualAvailableAmount()).negate()
                .subtract(getBigDecimal(allowPlacedOrderAmountResponse.getPendingReplyOrderAmount()).add(getBigDecimal(allowPlacedOrderAmountResponse.getPartReplyOrderAmount())))
                .setScale(2, RoundingMode.HALF_UP).toPlainString());

    }
    //查询可下预报单金额
    private AllowPlacedOrderAmountResponse getAllowPlacedOrderAmountResponse(String companyId){
        QueryAllowPlacedOrderAmountRequest queryAllowPlacedOrderAmountRequest = new QueryAllowPlacedOrderAmountRequest();
        queryAllowPlacedOrderAmountRequest.setCompanyId(companyId);
        Result<AllowPlacedOrderAmountResponse> allowPlacedOrderAmountResponseResult = allocateApplyOrderReadService.queryAllowPlacedOrderAmount(queryAllowPlacedOrderAmountRequest);
        if (allowPlacedOrderAmountResponseResult != null && allowPlacedOrderAmountResponseResult.isSuccess() &&
                allowPlacedOrderAmountResponseResult.getResult() != null){
            AllowPlacedOrderAmountResponse allowPlacedOrderAmountResponse = allowPlacedOrderAmountResponseResult.getResult();
            return allowPlacedOrderAmountResponse;
        }
        return new AllowPlacedOrderAmountResponse();
    }

    //查询冻结和未确认金额
    private FrozenAndUnconfirmedAmountResponse getFrozenAndUnconfirmedAmountResponse(String companyId){
        QueryFrozenAndUnconfirmedAmountRequest frozenAndUnconfirmedAmountRequest = new QueryFrozenAndUnconfirmedAmountRequest();
        frozenAndUnconfirmedAmountRequest.setCompanyId(companyId);
        Result<FrozenAndUnconfirmedAmountResponse> frozenAndUnconfirmedAmountResponseResult = allocateOrderReadService.queryFrozenAndUnconfirmedAmount(frozenAndUnconfirmedAmountRequest);
        if (frozenAndUnconfirmedAmountResponseResult != null && frozenAndUnconfirmedAmountResponseResult.isSuccess()
                && frozenAndUnconfirmedAmountResponseResult.getResult() != null){
            FrozenAndUnconfirmedAmountResponse frozenAndUnconfirmedAmountResponse = frozenAndUnconfirmedAmountResponseResult.getResult();
            return frozenAndUnconfirmedAmountResponse;
        }
        return new FrozenAndUnconfirmedAmountResponse();
    }

    /**
     * 校验请求参数
     * @param callbackRequest
     */
    private void checkRequest(CreditCallbackRequest callbackRequest){
        if (Objects.isNull(callbackRequest)){
            throw new FacadeException("OTS-07-008-01-16-020");
        }
        SapMessageHeader messageHeader = callbackRequest.getMessageHeader();
        List<MnSap020CallbackSDO> data = callbackRequest.getData();
        //时间戳空值校验
        //异步消息是成功还是错误的, 错误就不需要校验太多信息了.
        if (messageHeader == null){
            throw new FacadeException("OTS-07-008-01-16-024");
        }
        if (StringUtils.isBlank(messageHeader.getSENDTIME())){
            throw new FacadeException("OTS-07-008-01-16-022");
        }
        if (CollectionUtils.isEmpty(data)){
            throw new FacadeException("OTS-07-008-01-16-025");
        }
    }
//    /**
//     * 参数校验
//     * @param callbackRequest
//     */
//    private void checkParams(CreditCallbackRequest callbackRequest){
//        if (Objects.isNull(callbackRequest)){
//            throw new FacadeException("OTS-07-008-01-16-020");
//        }
//        SapMessageHeader messageHeader = callbackRequest.getMessageHeader();
//        List<MnSap020CallbackSDO> data = callbackRequest.getData();
//        //时间戳空值校验
//        //异步消息是成功还是错误的, 错误就不需要校验太多信息了.
//        if (messageHeader == null){
//            throw new FacadeException("OTS-07-008-01-16-024");
//        }
//        if (StringUtils.isBlank(messageHeader.getSENDTIME())){
//            throw new FacadeException("OTS-07-008-01-16-022");
//        }
//        if (CollectionUtils.isEmpty(data)){
//            throw new FacadeException("OTS-07-008-01-16-025");
//        }
//        //行数据校验
//        data.forEach(it -> {
//            checkParams(it);
//            //参数值就暂时不校验了. 合法性
//        });
//        //校验soldPartCode的合法性
//        Map<String, OrganizationSDO> organizationSDOMap = Maps.newHashMap();
//        BaselineGetOrganizationByCodes2Request queryRequest = new BaselineGetOrganizationByCodes2Request();
//        queryRequest.setIds(data.stream().map(MnSap020CallbackSDO::getSoldPartCode).distinct().collect(Collectors.toList()));
//        BaselineGetOrganizationByCodes2Response response = baseDataService.baselineGetOrganizationByCodes2(queryRequest);
//        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
//            response.getResult().forEach(organizationSDO -> {
//                organizationSDOMap.put(organizationSDO.getCode(),organizationSDO);
//            });
//        }
//        data.forEach(it->{
//            if (!organizationSDOMap.containsKey(it.getSoldPartCode().toString())){
//                throw new FacadeException("OTS-07-008-01-16-027");
//            }
//        });
//
//    }

    /**
     * 获取组织map
     * @param request
     * @return
     */
    private Map<String, OrganizationSDO> getOrganizationMap(CreditCallbackRequest request){
        Map<String, OrganizationSDO> organizationSDOMap = Maps.newHashMap();
        BaselineGetOrganizationByCodes2Request queryRequest = new BaselineGetOrganizationByCodes2Request();
        queryRequest.setIds(request.getData().stream().map(MnSap020CallbackSDO::getSoldPartCode).distinct().collect(Collectors.toList()));
        BaselineGetOrganizationByCodes2Response response = baseDataService.baselineGetOrganizationByCodes2(queryRequest);
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            response.getResult().forEach(organizationSDO -> {
                organizationSDOMap.put(organizationSDO.getCode(),organizationSDO);
            });
        }
        return organizationSDOMap;
    }

    //可发货余额=应收总额+在途资金+未走量-信贷限额-可用费用金额
    private String calculate(String receivableBalance,
                             String transitAmount,
                             String unShipAmount,
                             String totalCreditBalance,
                             String creditBalance){
        return getBigDecimal(receivableBalance).add(getBigDecimal(transitAmount))
                .add(getBigDecimal(unShipAmount))
                .subtract(getBigDecimal(totalCreditBalance)).subtract(getBigDecimal(creditBalance)).toString();
    }
    private BigDecimal getBigDecimal(String value){
        return StringUtils.isBlank(value) ? BigDecimal.ZERO : new BigDecimal(value.trim());
    }

//    /**
//     * 获取售达方编码 分子公司
//     * @param callbackRequest
//     * @return
//     */
//    private String getSoldPartCode(CreditCallbackRequest callbackRequest){
//        if (Objects.isNull(callbackRequest)){
//            throw new FacadeException("OTS-07-008-01-16-020");
//        }
//        List<MnSap020CallbackSDO> data = callbackRequest.getData();
//        if (CollectionUtils.isEmpty(data)){
//            throw new FacadeException("OTS-07-008-01-16-025");
//        }
//        Integer soldPartCode = data.get(0).getSoldPartCode();
//        if (soldPartCode == null){
//            throw new FacadeException("OTS-07-008-01-16-004");
//        }
//        return soldPartCode.toString();
//    }

    /**
     * 根据编码查询组织
     * @param soldPartCode
     * @return
     */
    private OrganizationSDO getOrganizationSDO(String soldPartCode){
        BaselineGetOrganizationByCodes2Request baselineGetOrganizationByCodes2Request = new BaselineGetOrganizationByCodes2Request();
        baselineGetOrganizationByCodes2Request.setIds(Lists.newArrayList(soldPartCode));
        baselineGetOrganizationByCodes2Request.setStatus(1);
        BaselineGetOrganizationByCodes2Response response = baseDataService.baselineGetOrganizationByCodes2(baselineGetOrganizationByCodes2Request);
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())){
            return response.getResult().get(0);
        }
        return new OrganizationSDO();
    }


    /**
     * 构建信贷数据 包含分子公司可发货余额
     * @param sdo
     * @return
     */
    private Credit buildCredit(MnSap020CallbackSDO sdo){
        Credit credit = new Credit();

        credit.setSaleOrganizationCode(sdo.getSaleOrganizationCode().toString());
        credit.setSapChannel(sdo.getSapChannel().toString());
        credit.setProductGroupCode(sdo.getProductGroupCode().toString());
        credit.setSoldPartCode(sdo.getSoldPartCode().toString());
        //信贷限额
        credit.setCreditLimit(sdo.getCreditLimit());
        //应收余额
        credit.setReceivableBalance(sdo.getReceivableBalance());
        //在途资金
        credit.setTransitAmount(sdo.getTransitAmount());
        //未走量
        credit.setUnShipAmount(sdo.getUnShipAmount());
        //信贷风险总额
        credit.setTotalCreditBalance(sdo.getTotalCreditBalance());
        //可用费用余额
        credit.setCreditBalance(sdo.getCreditBalance());
        //可发货余额=应收总额+在途资金+未走量-信贷限额-可用费用金额
        credit.setAvailableBalance(calculate(sdo.getReceivableBalance(), sdo.getTransitAmount(),sdo.getUnShipAmount(),
                sdo.getCreditLimit(),sdo.getCreditBalance()));
        //组织id需要调用接口查询
        OrganizationSDO organizationSDO = getOrganizationSDO(sdo.getSoldPartCode().toString());
        credit.setCompanyId(organizationSDO.getId());
        credit.setCompanyName(organizationSDO.getName());
        //其他计算字段
        fillCredit(credit);
        return credit;
    }

    //去空格
    private void trim(MnSap020CallbackSDO it){
        it.setCreditLimit(it.getCreditLimit().trim());
        it.setReceivableBalance(it.getReceivableBalance().trim());
        it.setTransitAmount(it.getTransitAmount().trim());
        it.setUnShipAmount(it.getUnShipAmount().trim());
        it.setTotalCreditBalance(it.getTotalCreditBalance().trim());
        it.setCreditBalance(it.getCreditBalance().trim());
    }

    //因为sap的负号在末尾, 变换负号
    private void changeNegativePosition(MnSap020CallbackSDO sdo){
        if (sdo.getCreditLimit().contains(NEGATIVE)){
            sdo.setCreditLimit(changeNegativePosition(sdo.getCreditLimit()));
        }
        if (sdo.getReceivableBalance().contains(NEGATIVE)){
            sdo.setReceivableBalance(changeNegativePosition(sdo.getReceivableBalance()));
        }
        if (sdo.getTransitAmount().contains(NEGATIVE)){
            sdo.setTransitAmount(changeNegativePosition(sdo.getTransitAmount()));
        }
        if (sdo.getUnShipAmount().contains(NEGATIVE)){
            sdo.setUnShipAmount(changeNegativePosition(sdo.getUnShipAmount()));
        }
        if (sdo.getTotalCreditBalance().contains(NEGATIVE)){
            sdo.setTotalCreditBalance(changeNegativePosition(sdo.getTotalCreditBalance()));
        }
        if (sdo.getCreditBalance().contains(NEGATIVE)){
            sdo.setCreditBalance(changeNegativePosition(sdo.getCreditBalance()));
        }
    }
    //负号倒转
    private String changeNegativePosition(String number){
        return NEGATIVE + number.replaceAll(NEGATIVE,"");
    }

    //是否是数字
    private void isNumber(MnSap020CallbackSDO it){
        if (!NumberUtils.isCreatable(it.getReceivableBalance())) {
            throw new FacadeException("OTS-07-008-01-16-026","receivableBalance");
        }
        if (!NumberUtils.isCreatable(it.getTransitAmount())) {
            throw new FacadeException("OTS-07-008-01-16-026","transitAmount");
        }
        if (!NumberUtils.isCreatable(it.getUnShipAmount())) {
            throw new FacadeException("OTS-07-008-01-16-026","unShipAmount");
        }
        if (!NumberUtils.isCreatable(it.getTotalCreditBalance())) {
            throw new FacadeException("OTS-07-008-01-16-026","totalCreditBalance");
        }
        if (!NumberUtils.isCreatable(it.getCreditLimit())){
            throw new FacadeException("OTS-07-008-01-16-026","creditLimit");
        }
        if (!NumberUtils.isCreatable(it.getCreditBalance())){
            throw new FacadeException("OTS-07-008-01-16-026","creditBalance");
        }
    }

    //校验数据
    private void checkParams(MnSap020CallbackSDO it){
        isBlank(it);
        //去空格
        trim(it);
        //转换负号
        changeNegativePosition(it);
        //是否数字
        isNumber(it);
    }

    //属性值校验
    private void isBlank(MnSap020CallbackSDO it){

        if (it.getSaleOrganizationCode() == null){
            throw new FacadeException("OTS-07-008-01-16-001");
        }
        if (!SALE_ORGANIZATION_CODE.equals(it.getSaleOrganizationCode().toString())){
            throw new FacadeException("OTS-07-008-01-16-011");
        }
        if (it.getSapChannel() == null){
            throw new FacadeException("OTS-07-008-01-16-002");
        }
        if (!SAP_CHANNEL.equals(it.getSapChannel().toString())){
            throw new FacadeException("OTS-07-008-01-16-012");
        }
        if (it.getProductGroupCode() == null){
            throw new FacadeException("OTS-07-008-01-16-003");
        }
        if (!PRODUCT_GROUP_CODE.equals(it.getProductGroupCode().toString())){
            throw new FacadeException("OTS-07-008-01-16-013");
        }
        if (it.getSoldPartCode() == null){
            throw new FacadeException("OTS-07-008-01-16-004");
        }
        if (StringUtils.isBlank(it.getCreditLimit())){
            throw new FacadeException("OTS-07-008-01-16-005");
        }
        if (StringUtils.isBlank(it.getReceivableBalance())){
            throw new FacadeException("OTS-07-008-01-16-006");
        }
        if (StringUtils.isBlank(it.getTransitAmount())){
            throw new FacadeException("OTS-07-008-01-16-007");
        }
        if (StringUtils.isBlank(it.getUnShipAmount())){
            throw new FacadeException("OTS-07-008-01-16-008");
        }
        if (StringUtils.isBlank(it.getTotalCreditBalance())){
            throw new FacadeException("OTS-07-008-01-16-009");
        }
        if (StringUtils.isBlank(it.getCreditBalance())){
            throw new FacadeException("OTS-07-008-01-16-010");
        }
    }
}
